package md.mru.frontend.controllers;

import md.mru.core.domains.type.EventType;
import md.mru.core.domains.type.NodeType;
import md.mru.core.domains.type.TreeChangesType;
import md.mru.core.dtos.*;
import md.mru.core.service.AdministrationService;
import md.mru.core.service.TreeService;
import md.mru.frontend.models.TreeContextMenuModel;
import md.mru.frontend.utils.FolderStateType;
import org.primefaces.context.RequestContext;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.event.TreeDragDropEvent;
import org.primefaces.model.CheckboxTreeNode;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import org.primefaces.model.menu.DefaultMenuItem;
import org.primefaces.model.menu.MenuElement;
import org.primefaces.model.menu.MenuModel;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import java.util.*;

/**
 * @author sergiu.marin
 * @since 12.04.2014.
 */
@ManagedBean(name = "treeAdministrationBean")
@ViewScoped
public class TreeAdministrationBean extends BackingBean {

    private static final long serialVersionUID = 1612454877681660019L;
    private TreeNode rootModel;
    private TreeNode administrationRootModel;
    private TreeNode selectedTreeNode;
    private TreeNode[] selectedTreeNodes;
    private String writeRoleSelection;
    private boolean treeLoaded = false;
    @ManagedProperty(value = "#{treeService}")
    private TreeService treeService;
    @ManagedProperty(value = "#{administrationService}")
    private AdministrationService administrationService;
    @ManagedProperty(value = "#{treeContextMenuModel}")
    private TreeContextMenuModel treeContextMenuModel;
    @ManagedProperty(value = "#{folderAdministrationBean}")
    private FolderAdministrationBean folderAdministrationBean;
    @ManagedProperty(value = "#{authenticationBean}")
    private AuthenticationBean authenticationBean;
    private TreeNodeModelDto treeNode;
    private boolean moveActivated;
    private boolean administrationActivated;
    private List<TreeNodeTypeDto> treeNodeTypes;
    private List<UserGroupDto> groups;
    private Long selectedGroupId;
    private MenuModel menuModel;
    private Comparator<TreeNode> TREE_NODE_COMPARATOR = new Comparator<TreeNode>() {
        @Override
        public int compare(TreeNode node1, TreeNode node2) {
            Double position1 = ((TreeNodeModelDto) node1.getData()).getPosition();
            Double position2 = ((TreeNodeModelDto) node2.getData()).getPosition();
            return position1.compareTo(position2);
        }
    };

    @PostConstruct
    public void initTree() {
        Map<Long, DefaultTreeNode> mapTreeModels = new LinkedHashMap<>(0);
        this.rootModel = new DefaultTreeNode(NodeType.FOLDER.name(), "Root", null);
        String type;
        TreeNode treeNode = new DefaultTreeNode(NodeType.STATIC_FOLDER.name(), new TreeNodeModelDto("Serviciul vamal"), rootModel);
        List<TreeNodeModelDto> nodeModels = treeService.loadTreeNodeModels(authenticationBean.getLoginUser().getUser().getUserGroup().getId());
        for (TreeNodeModelDto nodeModel : nodeModels) {
            if (!nodeModel.getGroups().iterator().next().getCanWrite()) {
                type = NodeType.READ_ONLY.name();
            } else if (hasActiveAttachedPerson(nodeModel.getTreeFolders())) {
                type = NodeType.ATTACHED_PERSON.name();
            } else if (nodeModel.getTreeNodeType().getNodeType().equals(NodeType.POSITION)) {
                type = NodeType.POSITION.name();
            } else {
                type = NodeType.FOLDER.name();
            }
            mapTreeModels.put(nodeModel.getId(), new DefaultTreeNode(type, nodeModel, null));
        }

        for (DefaultTreeNode mapNode : mapTreeModels.values()) {
            TreeNodeModelDto data = (TreeNodeModelDto) mapNode.getData();
            if (data.getParentNode() == null) {
                mapNode.setParent(treeNode);
                mapNode.getParent().getChildren().add(mapNode);
            } else {
                DefaultTreeNode parentNode = mapTreeModels.get(data.getParentNode().getId());
                mapNode.setParent(parentNode);
                mapNode.getParent().getChildren().add(mapNode);
            }
        }
    }

    private boolean hasActiveAttachedPerson(Set<TreeFolderDto> treeFolders) {
        if (treeFolders.isEmpty()) {
            return false;
        }
        for (TreeFolderDto treeFolder : treeFolders) {
            if (treeFolder.isActive()) {
                return true;
            }
        }
        return false;
    }

    public void onTreeNodeTypeSelect() {
        if (isPositionTreeNodeType()) {
            this.treeNode.setName(this.treeNode.getTreeNodeType().getName());
        }
    }

    public boolean isPositionTreeNodeType() {
        return this.treeNode.getTreeNodeType() != null && this.treeNode.getTreeNodeType().getNodeType().equals(NodeType.POSITION);
    }

    public void loadTreeNodeModels() {
        Map<Long, CheckboxTreeNode> mapTreeModels = new HashMap<Long, CheckboxTreeNode>(0);
        this.administrationRootModel = new CheckboxTreeNode("Root", null);
        this.administrationRootModel.setSelected(true);
        this.administrationRootModel.setExpanded(true);
        TreeNode treeNode = new CheckboxTreeNode(new TreeNodeModelDto("Serviciul vamal"), administrationRootModel);
        treeNode.setSelected(true);
        treeNode.setExpanded(true);
        //this.selectedTreeNodes = new TreeNode[]{treeNode};
        List<TreeNodeModelDto> nodeModels = treeService.loadTreeNodeModels();
        for (TreeNodeModelDto nodeModel : nodeModels) {
            mapTreeModels.put(nodeModel.getId(), new CheckboxTreeNode(nodeModel, null));
        }

        for (CheckboxTreeNode mapNode : mapTreeModels.values()) {
            TreeNodeModelDto data = (TreeNodeModelDto) mapNode.getData();
            if (data.getParentNode() == null) {
                mapNode.setParent(treeNode);
                mapNode.getParent().getChildren().add(mapNode);
            } else {
                CheckboxTreeNode parentNode = mapTreeModels.get(data.getParentNode().getId());
                mapNode.setParent(parentNode);
                mapNode.getParent().getChildren().add(mapNode);
            }
        }
    }

    public void onChangeGroup() {
        this.resetTreeModel(administrationRootModel);
        this.writeRoleSelection = "";
        if (selectedGroupId != null) {
                /*RootTreeModelDto rootView = treeService.getGroupRootView(selectedGroupId);
                rootModel = rootView.getRoot();*/
            List<TreeModelUserGroupDto> treeModelUserGroups = treeService.loadTreeGroupModel(selectedGroupId);

            Set<Long> groupDisplayNodes = new HashSet<Long>();
            Set<Long> groupCanWriteNodes = new HashSet<Long>();
            for (TreeModelUserGroupDto ng : treeModelUserGroups) {
                groupDisplayNodes.add(ng.getId().getTreeNodeModel().getId());
                if (ng.getCanWrite()) {
                    groupCanWriteNodes.add(ng.getId().getTreeNodeModel().getId());
                }
            }
            Set<String> rowKeys = new HashSet<String>();
            List<TreeNode> selectedTreeNodes = new ArrayList<>();
            this.getNodeRowKeys(rowKeys, administrationRootModel, groupCanWriteNodes, groupDisplayNodes, selectedTreeNodes);
            boolean first = true;
            for (String rowKey : rowKeys) {
                if (!first) {
                    this.writeRoleSelection += ",";
                }
                first = false;
                this.writeRoleSelection += rowKey;
            }
            this.selectedTreeNodes = selectedTreeNodes.toArray(new TreeNode[selectedTreeNodes.size()]);
        }
    }

    private void resetTreeModel(TreeNode treeNode) {
        treeNode.setSelected(false);
        for (TreeNode child : treeNode.getChildren()) {
            this.resetTreeModel(child);
        }
    }

    private void getNodeRowKeys(Set<String> rowKeys, TreeNode nodeModel, Set<Long> canWriteNodes, Set<Long> groupDisplayNodes, List<TreeNode> selectedTreeNodes) {
        if (nodeModel.getData() instanceof TreeNodeModelDto) {
            if (canWriteNodes.contains(((TreeNodeModelDto) nodeModel.getData()).getId())) {
                rowKeys.add(nodeModel.getRowKey());
            }

            if (groupDisplayNodes.contains(((TreeNodeModelDto) nodeModel.getData()).getId())) {
                selectedTreeNodes.add(nodeModel);
                nodeModel.setSelected(true);
                nodeModel.setExpanded(true);
            }
        }
        for (TreeNode child : nodeModel.getChildren()) {
            this.getNodeRowKeys(rowKeys, child, canWriteNodes, groupDisplayNodes, selectedTreeNodes);
        }
    }

    @Deprecated
    private void loadTree() {
        updateTree();
        treeLoaded = true;
        //Thread thr = new Thread(run);
        //thr.start();
    }

    public void onNodeSelect(NodeSelectEvent event) {
        //this.setupTreeContextMenu();
        //RequestContext.getCurrentInstance().addCallbackParam("menuItem_type", true);
        String breadCrump = this.buildBreadCrump(event.getTreeNode());
        utilAdministrationBean.setBreadCrump(breadCrump);
    }

    public void displayAttachFolderDialog() {
        /*TreeNodeModelDto nodeModel = (TreeNodeModelDto) this.selectedTreeNode.getData();
        if (!nodeModel.getTreeFolders().isEmpty()) {
            if (nodeModel.getTreeFolders().size() > 1) {
                *//*FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
                        "Comanda eronata",
                        "Functia selectata are persoane asignate corescunzator. " +
                        "Persoana de baza si persoana ce inlocuieste.");
                RequestContext.getCurrentInstance().showMessageInDialog(message);*//*
                RequestContext.getCurrentInstance().addCallbackParam("dialog_type", 1);
                return;
            }
            if (nodeModel.getTreeFolders().iterator().next().isActive()) {
                *//*FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
                        "Comanda eronata",
                        "Functia selectata are o persoana activa atasata. " +
                        "Pentru a atasa alta persoana, schimbati starea persoanei curente, " +
                        "de ex: Concediu, Concediu de boala, Eliberat din functie, s.a.");
                RequestContext.getCurrentInstance().showMessageInDialog(message);*//*
                RequestContext.getCurrentInstance().addCallbackParam("dialog_type", 2);
                return;
            }
        }
        RequestContext.getCurrentInstance().addCallbackParam("dialog_type", 0);*/
        //this.folderAdministrationBean.initEmploymentOrderDialog();
    }

    public void viewFolder() {
        Set<TreeFolderDto> treeFolders = ((TreeNodeModelDto) selectedTreeNode.getData()).getTreeFolders();
        if (treeFolders != null && !treeFolders.isEmpty()) {
            this.folderAdministrationBean.setSelectedFolder(treeFolders.iterator().next().getId().getFolder());
        }
    }

    /*public Runnable run = new Runnable() {
        @Override
        public void run() {
            try {
                updateTree();
                treeLoaded = true;
            } catch (Exception e) {
                System.out.println("" + e);
            }

        }
    };*/

    @Deprecated
    public void updateTree() {
        rootModel = treeService.getRootView().getRoot();
        selectedTreeNode = null;
    }

    public void setupTreeNodeDialog(String action) {
        if (treeNodeTypes == null) {
            treeNodeTypes = treeService.getTreeTypes();
            getObjectMappingConverter().mapObjectList(treeNodeTypes);
        }
        if (action.equals("add")) {
            this.treeNode = new TreeNodeModelDto();
        } else {
            //this.treeNode = treeService.getTreeNode(((TreeNodeModelDto) selectedTreeNode.getData()).getId());
            this.treeNode = (TreeNodeModelDto) selectedTreeNode.getData();
        }
    }

    public void saveTreeNode() {
        if (treeNode.getId() != 0) {
            treeService.update(treeNode/*, (TreeNodeModelDto) selectedTreeNode.getData()*/);
            String nodePath = this.buildBreadCrump(selectedTreeNode) + " > " + treeNode.getName();
            utilAdministrationBean.createNewEvent(new EventDto(EventType.TREE, nodePath, TreeChangesType.UPDATED, authenticationBean.getLoginUser().getUser()));
            //((TreeNodeModelDto) selectedTreeNode.getData()).setName(treeNode.getName());
            selectedTreeNode.setExpanded(true);
        } else {
            treeNode.setPosition((double) selectedTreeNode.getChildCount() + 1);
            TreeNodeModelDto parentData = (TreeNodeModelDto) selectedTreeNode.getData();
            if (parentData.getId() != 0) {
                treeNode.setParentNode(parentData);
            }
            //treeNode.getGroups().add(new TreeModelUserGroupDto(treeNode, authenticationBean.getLoginUser().getUser().getUserGroup(), true));
            long nodeId = treeService.saveTreeNode(treeNode);
            String nodePath = this.buildBreadCrump(selectedTreeNode) + " > " + treeNode.getName();
            utilAdministrationBean.createNewEvent(new EventDto(EventType.TREE, nodePath, TreeChangesType.CREATED, authenticationBean.getLoginUser().getUser()));
            if (nodeId != -1) {
                treeNode.setId(nodeId);
                TreeModelUserGroupDto treeNodeGroup = new TreeModelUserGroupDto(treeNode, authenticationBean.getLoginUser().getUser().getUserGroup(), true);
                treeService.saveTreeNodeGroup(treeNodeGroup);
                if (treeNode.getTreeNodeType().getNodeType().equals(NodeType.POSITION)) {
                    new DefaultTreeNode(NodeType.POSITION.name(), treeNode, selectedTreeNode);
                } else {
                    new DefaultTreeNode(NodeType.FOLDER.name(), treeNode, selectedTreeNode);
                }
                selectedTreeNode.setExpanded(true);
            }
        }
    }

    public void attachPersonToNode(FolderDto folder) {
        TreeNodeModelDto nodeModel = (TreeNodeModelDto) this.selectedTreeNode.getData();
        TreeFolderDto newTreeFolder = new TreeFolderDto();
        newTreeFolder.getId().setTreeNodeModel(nodeModel);
        newTreeFolder.getId().setFolder(folder);
        newTreeFolder.setBase(nodeModel.getTreeFolders().isEmpty());
        newTreeFolder.setActive(true);
        treeService.saveTreeFolder(newTreeFolder);
        nodeModel.getTreeFolders().add(newTreeFolder);
        ((DefaultTreeNode) this.selectedTreeNode).setType("ATTACHED_PERSON");
        this.selectedTreeNode.setExpanded(true);
    }

    public void menuItemLabel() {
        if (this.selectedTreeNode != null) {
            TreeNodeModelDto nodeModel = (TreeNodeModelDto) this.selectedTreeNode.getData();
            if (nodeModel.getTreeNodeType().getNodeType().equals(NodeType.FOLDER)) {
                RequestContext.getCurrentInstance().addCallbackParam("menuItem_type", true);
                //return "Adauga";
            } else {
                //return "Ataseaza dosar";
                RequestContext.getCurrentInstance().addCallbackParam("menuItem_type", false);
            }
        }
//        return "";
    }

    public void setupTreeContextMenu() {
        if (this.isFolderType()) {
            List<MenuElement> elements = treeContextMenuModel.getMenuModel().getElements();
            for (MenuElement element : elements) {
                if (((DefaultMenuItem) element).getStyleClass().equals("test")) {
                    element = new DefaultMenuItem("X");
                }
            }
        } else {
            List<MenuElement> elements = treeContextMenuModel.getMenuModel().getElements();
            for (MenuElement element : elements) {
                if (element.getId().equals("menu-item-to-change")) {
                    element = new DefaultMenuItem("Y");
                }
            }
        }
    }

    private String getOnCompleteJs() {
        TreeNodeModelDto nodeModel = (TreeNodeModelDto) this.selectedTreeNode.getData();
        if (!nodeModel.getTreeFolders().isEmpty()) {
            if (nodeModel.getTreeFolders().size() > 1) {
                return "PF('no-new-person').show()";
            }
            if (nodeModel.getTreeFolders().iterator().next().isActive()) {
                return "PF('already-active-person').show()";
            }
        }
        return "PF('treeAddOrder').show()";
    }

    private boolean isFolderType() {
        TreeNodeModelDto nodeModel = (TreeNodeModelDto) this.selectedTreeNode.getData();
        return nodeModel.getTreeNodeType().getNodeType().equals(NodeType.FOLDER);
    }

    /*public void saveOrder() {
        this.folderAdministrationBean.createOrder();

    }*/

    public void transferPersonToNewNode(FolderDto folder) {
        TreeNodeModelDto nodeModel = (TreeNodeModelDto) this.selectedTreeNode.getData();
        TreeFolderDto newTreeFolder = new TreeFolderDto();
        newTreeFolder.setActive(true);
        newTreeFolder.setBase(true);
        newTreeFolder.setValidFrom(new Date());
        newTreeFolder.setId(new TreeFolderIdDto(nodeModel, folder));

        TreeNode treeNode = this.getTreeNode(this.rootModel, folder);
        TreeNodeModelDto treeNodeModel = (TreeNodeModelDto) treeNode.getData();
        TreeFolderDto foundFolder = this.retrieveNodeFolderById(treeNodeModel.getTreeFolders(), folder.getId());
        treeNodeModel.getTreeFolders().remove(foundFolder);
        treeService.removeTreeFolderLink(foundFolder);
        nodeModel.getTreeFolders().add(newTreeFolder);
        treeService.saveTreeFolder(newTreeFolder);
        ((DefaultTreeNode) treeNode).setType(NodeType.POSITION.name());
        ((DefaultTreeNode) this.selectedTreeNode).setType("ATTACHED_PERSON");
        this.selectedTreeNode.setExpanded(true);
    }

    private TreeFolderDto retrieveNodeFolderById(Set<TreeFolderDto> nodeFolders, long folderId) {
        for (TreeFolderDto nodeFolder : nodeFolders) {
            if (nodeFolder.getId().getFolder().getId() == folderId) {
                return nodeFolder;
            }
        }
        return null;
    }

    public void removeFolderFromNode(FolderDto folder) {
        TreeNodeModelDto treeNodeModel = (TreeNodeModelDto) this.selectedTreeNode.getData();
        TreeFolderDto foundFolder = this.retrieveNodeFolderById(treeNodeModel.getTreeFolders(), folder.getId());
        if (foundFolder != null) {
            treeNodeModel.getTreeFolders().remove(foundFolder);
            treeService.removeTreeFolderLink(foundFolder);
            foundFolder.setActive(true);
            ((DefaultTreeNode) this.selectedTreeNode).setType(NodeType.POSITION.name());
            this.selectedTreeNode.setExpanded(true);
        }
    }

    public void changeNodeState(FolderDto folder) {
        TreeNodeModelDto treeNodeModel = (TreeNodeModelDto) this.selectedTreeNode.getData();
        TreeFolderDto foundFolder = this.retrieveNodeFolderById(treeNodeModel.getTreeFolders(), folder.getId());
        if (folder.getFolderState().isBlockPosition()) {
            foundFolder.setActive(false);
            ((DefaultTreeNode) this.selectedTreeNode).setType(NodeType.POSITION.name());
        } else {
            foundFolder.setActive(true);
        }
        treeService.saveTreeFolder(foundFolder);
        this.selectedTreeNode.setExpanded(true);
    }

    public void activateNodeFolder(FolderDto folder) {
        TreeNodeModelDto treeNodeModel = (TreeNodeModelDto) this.selectedTreeNode.getData();
        TreeFolderDto foundFolder = this.retrieveNodeFolderById(treeNodeModel.getTreeFolders(), folder.getId());
        if (!foundFolder.isActive()) {
            foundFolder.setActive(true);
            ((DefaultTreeNode) this.selectedTreeNode).setType("ATTACHED_PERSON");
        }
        treeService.saveTreeFolder(foundFolder);
        this.selectedTreeNode.setExpanded(true);
    }

    public void changeFolderState(OrderDto folder) {
        if (selectedTreeNode != null) {
            TreeNodeModelDto treeNodeModel = (TreeNodeModelDto) this.selectedTreeNode.getData();
            TreeFolderDto foundFolder = this.retrieveNodeFolderById(treeNodeModel.getTreeFolders(), folder.getId());
            if (foundFolder != null) {
                if (this.folderAdministrationBean.getSelectedFolder().getFolderState().getId() == FolderStateType.DISCHARGED.folderStateId
                        || this.folderAdministrationBean.getSelectedFolder().getFolderState().getId() == FolderStateType.DISCHARGED.folderStateId) {
                    treeNodeModel.getTreeFolders().remove(foundFolder);
                    treeService.removeTreeFolderLink(foundFolder);
                    foundFolder.setActive(true);
                    ((DefaultTreeNode) this.selectedTreeNode).setType(NodeType.POSITION.name());
                } else {
                    if (!this.folderAdministrationBean.getSelectedFolder().getFolderState().isBlockPosition()) {
                        foundFolder.setActive(false);
                        ((DefaultTreeNode) this.selectedTreeNode).setType(NodeType.POSITION.name());
                    } else {
                        foundFolder.setActive(true);
                    }
                    treeService.saveTreeFolder(foundFolder);
                }
                this.selectedTreeNode.setExpanded(true);
            }
        }
    }

    private TreeNode getTreeNode(TreeNode rootModel, FolderDto folder) {
        if (rootModel.getData() instanceof TreeNodeModelDto) {
            TreeNodeModelDto nodeModel = (TreeNodeModelDto) rootModel.getData();
            for (TreeFolderDto t : nodeModel.getTreeFolders()) {
                if (t.getId().getFolder().getId() == folder.getId()) {
                    return rootModel;
                }
            }
        }
        for (TreeNode child : rootModel.getChildren()) {
            TreeNode treeNode = this.getTreeNode(child, folder);
            if (treeNode != null) {
                return treeNode;
            }
        }
        return null;
    }

    /*private DefaultTreeNode removeTreeFolder(TreeNode rootModel, FolderDto folder) {
        TreeFolderDto foundTreeNode = null;
        TreeNodeModelDto nodeModel = null;
        if (rootModel.getData() instanceof TreeNodeModelDto) {
            nodeModel = (TreeNodeModelDto) rootModel.getData();
            for (TreeFolderDto t : nodeModel.getTreeFolders()) {
                if (t.getId().getFolder().getId() == folder.getId()) {
                    foundTreeNode = t;
                    break;
                }
            }
        }
        if (foundTreeNode != null) {
            nodeModel.getTreeFolders().remove(foundTreeNode);
            return new DefaultTreeNode(FunctionType.POSITION.name(), nodeModel, selectedTreeNode.getParent());

        } else {
            for (TreeNode child : rootModel.getChildren()) {
                this.removeTreeFolder(child, folder);
            }
        }
        return null;
    }*/

/*    public void saveRoleTreeNodes() {
        treeService.saveRoleTreeNodes(selectedTreeNodes, selectedGroupId);
    }*/

    public void displayContextMenu() {
        TreeNodeModelDto nodeModel = (TreeNodeModelDto) this.selectedTreeNode.getData();
        RequestContext.getCurrentInstance().addCallbackParam("menuItem_type", nodeModel.getGroups().iterator().next().getCanWrite());
    }

    public void onAdministrationTree() {
        if (administrationActivated) {
            groups = administrationService.getGroups();
            this.loadTreeNodeModels();
        }
    }

    public void saveGroupRoles() {
        Set<Long> canReadSelectedNodeIds = new HashSet<>();
        if (writeRoleSelection != null) {
            String[] values = this.writeRoleSelection.split(",");
            Set<String> roles = new HashSet<String>(Arrays.asList(values));
            collectWriteRoleSelectedNodes(rootModel, roles, canReadSelectedNodeIds);
        }
        List<TreeNodeModelDto> treeNodeModels = new ArrayList<>();
        for (TreeNode node : selectedTreeNodes) {
            TreeNodeModelDto nodeData = (TreeNodeModelDto) node.getData();
            if (nodeData.getId() != 0) {
                treeNodeModels.add(nodeData);
            }
            //this.collectTreeNodeModels(node, treeNodeModels);

        }
        //treeService.saveRoleTreeNodes(selectedTreeNodes, canReadSelectedNodeIds, selectedGroupId);
        treeService.saveRoleTreeNodes(treeNodeModels, canReadSelectedNodeIds, selectedGroupId);
    }

    /*private void collectTreeNodeModels(TreeNode node, Set<TreeNodeModelDto> treeNodeModels) {
        TreeNodeModelDto nodeData = (TreeNodeModelDto) node.getData();
        if (nodeData.getId() != 0) {
            treeNodeModels.add(nodeData);
        }
        *//*if (node.getParent() != null) {
            TreeNodeModelDto nodeData = (TreeNodeModelDto) node.getData();
            if (nodeData.getId() != 0) {
                treeNodeModels.add(nodeData);
            }*//*
        if (node.getParent() != null) {
            collectTreeNodeModels(node.getParent(), treeNodeModels);
        }
    }*/

    public void collectWriteRoleSelectedNodes(TreeNode node, Set<String> roles, Set<Long> nodeIds) {
        if (roles.contains(node.getRowKey())) {
            nodeIds.add(((TreeNodeModelDto) node.getData()).getId());
        }
        for (TreeNode child : node.getChildren()) {
            this.collectWriteRoleSelectedNodes(child, roles, nodeIds);
        }
    }

    public void onDragDrop(TreeDragDropEvent event) {
        TreeNodeModelDto nodeData = (TreeNodeModelDto) event.getDragNode().getData();
        double position = this.retrieveNodeInTree(rootModel.getChildren(), event.getDragNode());
        nodeData.setPosition(position);
        nodeData.setMoved(true);
    }

    private double retrieveNodeInTree(List<TreeNode> children, TreeNode draggedNode) {
        double newPos = 1, prev = 0, next;
        for (TreeNode node : children) {
            if (node.getRowKey().equals(draggedNode.getRowKey())) {
                int index = children.indexOf(node);
                if (index == children.size() - 1) {
                    newPos = children.size();
                } else {
                    if (index > 0) {
                        prev = ((TreeNodeModelDto) children.get(index - 1).getData()).getPosition();
                    }
                    next = ((TreeNodeModelDto) children.get(index + 1).getData()).getPosition();
                    newPos = (prev + next) / 2;
                }
                break;
            }
            if (draggedNode.getRowKey().startsWith(node.getRowKey())) {
                newPos = this.retrieveNodeInTree(node.getChildren(), draggedNode);
            }
        }
        return newPos;
    }

    public void onTreeNodeMove() {
        if (!moveActivated) {
            List<TreeNodeModelDto> movedNodes = new ArrayList<>();
            this.collectMovedTreeNodes(rootModel.getChildren(), movedNodes);
            treeService.updateTreeNodesPosition(movedNodes);
        }
    }

    public void collectMovedTreeNodes(List<TreeNode> children, List<TreeNodeModelDto> movedNodes) {
        for (TreeNode node : children) {
            TreeNodeModelDto nodeData = (TreeNodeModelDto) node.getData();
            if (nodeData.hasMoved()) {
                movedNodes.add(nodeData);
            }
            if (node.getChildren().size() > 1) {
                this.collectMovedTreeNodes(node.getChildren(), movedNodes);
            }
        }
    }

    /*public void changeMovedTreeNodesPosition(List<TreeNode> children) {
        for (TreeNode node : children) {
            NodeTreeModelDto nodeData = (NodeTreeModelDto) node.getData();
            if (nodeData.hasMoved()) {
                int index = children.indexOf(node);
                double position = 1, prev = 0, next = 1;

                if (index == children.size() - 1) {
                    position = children.size();
                } else {
                    if (index != 0) {
                        prev = ((NodeTreeModelDto) children.get(index - 1)).getFvr();
                    }
                    next = ((NodeTreeModelDto) children.get(index + 1)).getFvr();
                    position = (prev + next) / 2;
                }
                nodeData.setFvr(position);
            }
            this.changeMovedTreeNodesPosition(node.getChildren());
        }
    }*/

    public boolean isTreeFolderType() {
        return treeNode != null && treeNode.getTreeNodeType().getNodeType().equals(NodeType.FOLDER);
    }


    public TreeNode getRootModel() {
        return rootModel;
    }

    public TreeNode getAdministrationRootModel() {
        return administrationRootModel;
    }

    public TreeNode getSelectedTreeNode() {
        return selectedTreeNode;
    }

    public void setSelectedTreeNode(TreeNode selectedTreeNode) {
        this.selectedTreeNode = selectedTreeNode;
    }

    public TreeNode[] getSelectedTreeNodes() {
        return selectedTreeNodes;
    }

    public void setSelectedTreeNodes(TreeNode[] selectedTreeNodes) {
        this.selectedTreeNodes = selectedTreeNodes;
    }

    public boolean isTreeLoaded() {
        return treeLoaded;
    }

    public void setTreeService(TreeService treeService) {
        this.treeService = treeService;
    }

    public boolean isMoveActivated() {
        return moveActivated;
    }

    public void setMoveActivated(boolean moveActivated) {
        this.moveActivated = moveActivated;
    }

    public boolean isAdministrationActivated() {
        return administrationActivated;
    }

    public void setAdministrationActivated(boolean administrationActivated) {
        this.administrationActivated = administrationActivated;
    }

    public TreeNodeModelDto getTreeNode() {
        return treeNode;
    }

    public void setTreeNode(TreeNodeModelDto treeNode) {
        this.treeNode = treeNode;
    }

    public List<TreeNodeTypeDto> getTreeNodeTypes() {
        return treeNodeTypes;
    }

    public void setTreeNodeTypes(List<TreeNodeTypeDto> treeNodeTypes) {
        this.treeNodeTypes = treeNodeTypes;
    }

    public List<UserGroupDto> getGroups() {
        return groups;
    }

    public void setGroups(List<UserGroupDto> groups) {
        this.groups = groups;
    }

    public void setAdministrationService(AdministrationService administrationService) {
        this.administrationService = administrationService;
    }

    public Long getSelectedGroupId() {
        return selectedGroupId;
    }

    public void setSelectedGroupId(Long selectedGroupId) {
        this.selectedGroupId = selectedGroupId;
    }

    public String getWriteRoleSelection() {
        return writeRoleSelection;
    }

    public void setWriteRoleSelection(String writeRoleSelection) {
        this.writeRoleSelection = writeRoleSelection;
    }

    public void setFolderAdministrationBean(FolderAdministrationBean folderAdministrationBean) {
        this.folderAdministrationBean = folderAdministrationBean;
    }

    public MenuModel getMenuModel() {
        return menuModel;
    }

    public void setTreeContextMenuModel(TreeContextMenuModel treeContextMenuModel) {
        this.treeContextMenuModel = treeContextMenuModel;
    }

    public void setAuthenticationBean(AuthenticationBean authenticationBean) {
        this.authenticationBean = authenticationBean;
    }


}
